/*
 * Copyright (C) 2018 Weibo, Inc. All Rights Reserved.
 */
package com.fzy.common.util;

import cn.hutool.core.util.StrUtil;
import com.fzy.common.entity.ApiResult;
import com.fzy.common.enums.ErrorCode;
import com.fzy.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.RetryException;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 断言校验工具类
 *
 * @author zhaoyang10
 * @date 2018/9/26
 */
@Slf4j
public class Assert {

    private static final String MSG = "调用外部API返回信息:result={}";

    private Assert() {
    }

    /**
     * 检验字符串是否为空，为空抛异常
     */
    public static void notNull(String str, String msg) {
        if (null == str || str.trim().length() == 0) {
            throwEx(msg);
        }
    }

    public static void notNull(String str, ErrorCode errorCode) {
        if (null == str || str.trim().length() == 0) {
            throwEx(errorCode);
        }
    }

    /**
     * 检验字符串是否为空且最大长度限制，为空且超过最大长度抛异常
     */
    public static void notNull(String str, int maxLength, String msg) {
        if (null == str || str.trim().length() == 0 || str.length() > maxLength) {
            throwEx(msg);
        }
    }

    public static void notNull(String str, int maxLength, ErrorCode errorCode) {
        if (null == str || str.trim().length() == 0 || str.length() > maxLength) {
            throwEx(errorCode);
        }
    }

    /**
     * 检验数字是否为空且最大长度限制，为空且超过最大长度抛异常
     */
    public static void notNull(Integer num, int maxLength, String msg) {
        if (num == null || num.toString().length() > maxLength) {
            throwEx(msg);
        }
    }

    public static void notNull(Integer num, int maxLength, ErrorCode errorCode) {
        if (num == null || num.toString().length() > maxLength) {
            throwEx(errorCode);
        }
    }

    public static void notNull(BigDecimal num, int maxLength, String msg) {
        if (num == null || num.toString().length() > maxLength) {
            throwEx(msg);
        }
    }

    public static void notNull(BigDecimal num, int maxLength, ErrorCode errorCode) {
        if (num == null || num.toString().length() > maxLength) {
            throwEx(errorCode);
        }
    }

    /**
     * 检验最大长度不能超过maxLength 可以为空
     */
    public static void maxLength(Object obj, int maxLength, String msg) {
        if (obj != null) {
            if (obj instanceof String && ((String) obj).length() > maxLength) {
                throwEx(msg);
            }

            if (obj instanceof Integer && obj.toString().length() > maxLength) {
                throwEx(msg);
            }
        }
    }

    /**
     * 检验对象是否为null，为空抛异常
     */
    public static void notNull(Object obj, String msg) {
        if (obj == null) {
            throwEx(msg);
        }
    }

    public static void isNull(Object obj, String msg) {
        if (Objects.nonNull(obj)) {
            throwEx(msg);
        }
    }

    /**
     * 检验对象是否为null，为空抛异常
     */
    public static void notNull(Object obj, ErrorCode errorCode) {
        if (obj == null) {
            throwEx(errorCode);
        }
    }

    /**
     * 检验对象都不为null，其中一个为null抛异常
     */
    public static void notAllNull(List<Object> lists, ErrorCode errorCode) {
        for (Object obj : lists) {
            if (Objects.isNull(obj)) {
                throwEx(errorCode);
                return;
            }
        }
    }

    public static <E> void notNull(Collection<E> collection, ErrorCode errorCode) {
        if (collection == null || collection.isEmpty()) {
            throwEx(errorCode);
        }
    }

    /**
     * 校验条件状态值condition是否为true，不为true则抛异常
     */
    public static void assertTrue(boolean condition, String msg) {
        if (!condition) {
            throwEx(msg);
        }
    }

    public static void assertTrue(boolean condition, ErrorCode errorCode) {
        if (!condition) {
            throwEx(errorCode);
        }
    }

    /**
     * 校验条件状态值condition是否为false，不为false则抛异常
     */
    public static void assertFalse(boolean condition, String msg) {
        if (condition) {
            throwEx(msg);
        }
    }

    public static void assertFalse(boolean condition, ErrorCode errorCode) {
        if (condition) {
            throwEx(errorCode);
        }
    }

    /**
     * 检验统一异常处理
     */
    public static void throwEx(String msg) {
        throw new BusinessException(ErrorCode.PARAM_NOT_LEGAL, msg);
    }

    /**
     * 动态参数
     */
    public static void throwEx(ErrorCode code, String msg) {
        throw new BusinessException(code.getCode(), msg);
    }

    public static void throwEx(ErrorCode code, String template, Object... params) {
        String msg = StrUtil.format(template, params);
        throw new BusinessException(code.getCode(), msg);
    }

    public static void throwEx(Integer code, String msg) {
        throw new BusinessException(code, msg);
    }

    public static void throwEx(ErrorCode errorCode) {
        throw new BusinessException(errorCode);
    }

    public static <T> void throwEx(ApiResult<T> apiResult, String errorMsg) {
        if (apiResult == null) {
            throw new BusinessException(ErrorCode.API_SERVICE_ERROR, errorMsg);
        }
        throw new BusinessException(apiResult.getCode(), StrUtil.format("{}:[{}]", errorMsg, apiResult.getMessage()));
    }

    public static void throwEx(Throwable cause) {
        throw new BusinessException(cause);
    }

    /**
     * 检验调用外部API异常抛出错误信息
     */
    public static <T> void checkResult(ApiResult<T> apiResult) {
        log.info(MSG, apiResult);
        if (apiResult == null) {
            throwEx(ErrorCode.API_SERVICE_ERROR);
        }
        if (!apiResult.hasSuccess()) {
            throwEx(ErrorCode.API_SERVICE_ERROR, apiResult.getMessage());
        }
    }

    /**
     * 检验调用外部API异常抛出自定义错误信息
     */
    public static <T> void checkResult(ApiResult<T> apiResult, String errorMsg) {
        log.info(MSG, apiResult);
        if (apiResult == null) {
            throwEx(ErrorCode.API_SERVICE_ERROR);
        }
        if (!apiResult.hasSuccess()) {
            String msg = apiResult.getMessage();
            if (StringUtil.isNotNull(errorMsg)) {
                msg = StrUtil.format("{}:[{}]", errorMsg, apiResult.getMessage());
            }
            throw new BusinessException(apiResult.getCode(), msg);
        }
    }

    /**
     * 检验调用外部API异常抛出自定义错误信息
     *
     * @param apiResult apiResult
     * @param failCode  成功返回的code
     * @param errorMsg  自定义错误信息前缀
     */
    public static <T> void checkResult(ApiResult<T> apiResult, Integer failCode, String errorMsg) {
        log.info(MSG, apiResult);
        if (apiResult == null) {
            throwEx(ErrorCode.API_SERVICE_ERROR);
        }
        if (failCode.equals(apiResult.getCode())) {
            String msg = StrUtil.format("{}:[{}]", errorMsg, apiResult.getMessage());
            throw new BusinessException(apiResult.getCode(), msg);
        }
    }

    public static void bigDecimalEqual(BigDecimal source, BigDecimal target, String msg) {
        if (!Objects.equals(source, target) || source.compareTo(target) != 0) {
            throw new BusinessException(msg);
        }
    }

    public static void bigDecimalEqual(BigDecimal source, BigDecimal target, ErrorCode msg) {
        if (!Objects.equals(source, target) || source.compareTo(target) != 0) {
            throw new BusinessException(msg);
        }
    }

    /**
     * 如果source<target 抛异常
     */
    public static void assertGt(BigDecimal source, BigDecimal target, ErrorCode errorCode) {
        if (source.compareTo(target) < 0) {
            throw new BusinessException(errorCode);
        }
    }

    public static void assertGtZero(BigDecimal source, ErrorCode errorCode) {
        assertGt(source, BigDecimal.ZERO, errorCode);
    }


    public static void equals(Object source, Object target, String msg) {
        if (!Objects.equals(source, target)) {
            throw new BusinessException(msg);
        }
    }

    public static void equals(Object source, Object target, ErrorCode errorCode) {
        if (!Objects.equals(source, target)) {
            throw new BusinessException(errorCode);
        }
    }

    /**
     * 等于0 抛异常
     */
    public static void notZero(Integer source, String errMsg) {
        if (source.equals(0)) {
            throw new BusinessException(errMsg);
        }
    }


    public static void throwRetryEx(String msg) {
        throw new RetryException(msg);
    }
}
